#pragma once
#include <vector>
#include <algorithm>
#include "message.hpp"

namespace ns_log
{
    // FSBuffer自身线程不安全，但是在AsyncLooper当中是线程安全的, 且只有AsyncLooper才会访问该FSBuffer
    // 同理，LogMessageBuffer也是如此
    const size_t default_buff_size = 1024 * 1024; // 1MB  1,048,576 byte

    class FSBuffer
    {
    public:
        FSBuffer(size_t default_size = default_buff_size) : _writer(0), _reader(0), _default_size(default_size)
        {
            _buffer.resize(_default_size, '\0');
        }

        void push(const char *data, size_t len)
        {
            // 1. 扩容
            checkSize(len);
            // 2. 拷贝
            std::copy(data, data + len, &_buffer[_writer]);
            // 3. 移动写指针
            moveWriter(len);
        }

        const char *begin()
        {
            return &_buffer[_reader];
        }

        size_t writeableSize()
        {
            return _buffer.size() - _writer;
        }

        size_t readableSize()
        {
            return _writer - _reader;
        }

        void moveReader(size_t len)
        {
            _reader += len;
        }

        void reset()
        {
            _buffer.resize(_default_size, '\0');
            _writer = 0;
            _reader = 0;
        }

        void swap(FSBuffer &buffer)
        {
            _buffer.swap(buffer._buffer);
            std::swap(_writer, buffer._writer);
            std::swap(_reader, buffer._reader);
            std::swap(_default_size, buffer._default_size);
        }

        // 当readableSize为0时，代表缓冲区为空
        bool empty()
        {
            return readableSize() == 0;
        }

    private:
        void checkSize(size_t len)
        {
            if (writeableSize() < len)
            {
                // 加len是防止一次扩容依旧不够，为了简化代码，直接+len
                size_t newSize = 2 * _buffer.size() + len;
                _buffer.resize(newSize);
            }
        }

        void moveWriter(size_t len)
        {
            _writer += len;
        }

        std::vector<char> _buffer;
        size_t _writer;
        size_t _reader;
        size_t _default_size;
    };

    class LogMessageBuffer
    {
    public:
        LogMessageBuffer(size_t default_size = default_buff_size)
        {
            _buffer.reserve(default_size);
        }

        void push(const LogMessage::ptr &message)
        {
            if (_buffer.size() == _buffer.capacity())
            {
                _buffer.reserve(2 * _buffer.capacity());
            }
            _buffer.push_back(message);
        }

        bool empty()
        {
            return _buffer.empty();
        }

        bool full()
        {
            return _buffer.size() == _buffer.capacity();
        }

        size_t readableSize()
        {
            return _buffer.size();
        }

        

        void clear()
        {
            _buffer.clear();
        }

        std::vector<LogMessage::ptr> getBuffer()
        {
            return _buffer;
        }

    protected:
        std::vector<LogMessage::ptr> _buffer;
    };

    class DBBuffer : public LogMessageBuffer
    {
    public:
        DBBuffer(size_t default_size = default_buff_size)
            : LogMessageBuffer(default_size)
        {
        }
        void swap(DBBuffer &buffer)
        {
            _buffer.swap(buffer._buffer);
        }
    };

    class RemoteBuffer : public LogMessageBuffer
    {
    public:
        RemoteBuffer(size_t default_size = default_buff_size)
            : LogMessageBuffer(default_size)
        {
        }
        void swap(RemoteBuffer &buffer)
        {
            _buffer.swap(buffer._buffer);
        }
    };

}
